﻿using System;

namespace CirclesCenterCalculation
{
    class Program
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="x1">Current point = first point of tangency.</param>
        /// <param name="y1">Current point = first point of tangency.</param>
        /// <param name="x2">Old destination.</param>
        /// <param name="y2">Old destination.</param>
        /// <param name="x3">Destination.</param>
        /// <param name="y3">Destination.</param>
        /// <param name="R">Radius of the circle.</param>
        /// <param name="leftTurn"></param>
        /// <param name="x0">For circuls center.</param>
        /// <param name="y0">For circuls center.</param>
        public static void CalcCenter(double x1, double y1, double x2, double y2, double x3, double y3, double R, bool leftTurn, out double x0, out double y0)
        {
            double k, xed, yed, _xed, _yed;
            if (x2 != x1 && y2 != y1)
            {
                k = (y2 - y1) / (x2 - x1);
                xed = (x2 - x1) / Math.Abs(x2 - x1) * Math.Sqrt(1 / (1 + k * k));
                yed = k * xed;
                if (y1 > y2 == leftTurn)
                    _xed = Math.Sqrt(1 / (1 + (xed * xed) / (yed * yed)));
                else
                    _xed = -Math.Sqrt(1 / (1 + (xed * xed) / (yed * yed)));
                if (x2 > x1 == leftTurn)
                    _yed = Math.Sqrt(1 - _xed * _xed);
                else
                    _yed = -Math.Sqrt(1 - _xed * _xed);
            }
            else
            {
                if (x2 == x1)
                {
                    _yed = xed = 0;
                    yed = (y2 - y1) / Math.Abs(y2 - y1);
                    if (leftTurn)
                        _xed = -yed;
                    else
                        _xed = yed;
                }
                else
                {
                    _xed = yed = 0;
                    xed = (x2 - x1) / Math.Abs(x2 - x1);
                    if (leftTurn)
                        _yed = xed;
                    else
                        _yed = -xed;
                }
            }           
            x0 = R * _xed + x1;
            y0 = R * _yed + y1;
            CalcTangencyPoint(x0, y0, x3, y3, x1, y1, R);
        }

        /// <summary>
        /// Calculates the second point of tangency.
        /// </summary>
        /// <param name="x0">Circuls center.</param>
        /// <param name="y0">Circuls center.</param>
        /// <param name="x1">Destination.</param>
        /// <param name="y1">Destination.</param>
        /// <param name="x2">First point of tangency.</param>
        /// <param name="y2">First point of tangency.</param>
        /// <param name="R">Radius of the circle.</param>
        public static void CalcTangencyPoint(double x0, double y0, double x1, double y1, double x2, double y2, double R)
        {            
            /*double X = x0 - x1;
            double Y = y1 - y0;
            double P = X * Y / (X * X - R * R);
            double Q = (Y * Y - R * R) / (X * X - R * R);
            double k1 = P + Math.Sqrt(P * P - Q);
            double k2 = P - Math.Sqrt(P * P - Q);
            double k = k1;
            double a = k * k + 1;
            double b = -2 * (k * (k * x1 + y1) - y0) - x0;
            double x = -b / (2 * a);*/
            double X = x1 - x0;
            double Y = y1 - y0;
            double a = R * R - Y * Y;
            double b = 2 * X * Y;
            double c = R * R - X * X;
            double k1 = (-b + Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
            double k2 = (-b - Math.Sqrt(b * b - 4 * a * c)) / (2 * a);
            double k = k1;
            a = (k * k + 1);
            b = -2 * (k * (k * y1 - X) + y0);
            double y = -b / (2 * a);
            double _x1 = k1 * (y - y1) + x1;
            double _x2 = k2 * (y - y1) + x1;
            double phi1 = CalcAngle(x2, y2, _x1, y, R);
            double phi2 = CalcAngle(x2, y2, _x2, y, R);
            Console.Read();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="x1">First point of tangency.</param>
        /// <param name="y1">First point of tangency.</param>
        /// <param name="x2">Second point of tangency.</param>
        /// <param name="y2">Second point of tangency.</param>
        /// <param name="R">Radius of the circle.</param>
        /// <returns></returns>
        public static double CalcAngle(double x1, double y1, double x2, double y2, double R)
        {
            return Math.Acos(1 - ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) / (2 * R * R));
        }

        static void Main(string[] args)
        {
            double a, b;
            CalcCenter(50.0, 30.0, 120.0, 65.0, 95.0, 100.0, 45.0, true, out a, out b); 
        }
    }
}
